package cn.yshujia.repository;

import cn.yshujia.domain.entity.Like;
import cn.yshujia.mapper.LikeMapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;

import java.time.Duration;
import java.time.LocalTime;
import java.util.List;
import java.util.Set;

/**
 * @author YShuJia
 * @create 2024/12/20
 * @description LikeRepository
 */

@Repository
public class LikeRepository {
	
	@Resource
	RedisTemplate<String, Like> redis;
	
	@Resource
	LikeMapper mapper;
	
	private static final String LIKE_MAP = "like:record:";
	
	private static final Duration LIKE_DURATION = Duration.ofDays(3L);
	
	@Async ("Task")
	public void update(Long userId, Long sourceId) {
		String key = LIKE_MAP + userId;
		
		if (redis.opsForHash().hasKey(key, sourceId.toString())) {
			Boolean status = (Boolean) redis.opsForHash().get(key, sourceId.toString());
			redis.opsForHash().put(key, sourceId.toString(), Boolean.FALSE.equals(status));
		} else {
			Like like = new Like(userId, sourceId);
			mapper.insert(like);
			redis.opsForHash().put(key, sourceId.toString(), true);
		}
	}
	
	@Async ("Task")
	@Scheduled (cron = "0 0 3 3 * ?")
	public void initLike() {
		redis.delete(LIKE_MAP + "*");
		List<Like> list = mapper.selectList(null);
		for (Like like : list) {
			redis.opsForHash().put(LIKE_MAP + like.getUserId(), like.getSourceId().toString(), like.getStatus());
		}
		redis.expire(LIKE_MAP + "*", LIKE_DURATION);
	}
	
	
	/**
	 * [] * @return void
	 *
	 * @author YShuJia
	 * @description 每 3 个小时同步一次数据库 在 0-6 点之间不执行
	 * @author YShuJia
	 * @create 2025/3/14 20:08
	 */
	@Async ("Task")
	@Scheduled (cron = "0 0 */3 * * ?")
	public void synchronousMysql() {
		// 获取当前小时
		int currentHour = LocalTime.now().getHour();
		if (currentHour > 0 && currentHour < 6) {
			return;
		}
		Set<String> keys = redis.keys(LIKE_MAP + "*");
		if (ObjectUtils.isEmpty(keys)) {
			return;
		}
		for (String key : keys) {
			Set<Object> sourceIds = redis.opsForHash().keys(key);
			for (Object source : sourceIds) {
				Boolean status = (Boolean) redis.opsForHash().get(key, source);
				mapper.update(new LambdaUpdateWrapper<Like>()
						.set(Like::getStatus, status)
						.eq(Like::getSourceId, Long.parseLong(source.toString()))
						.eq(Like::getUserId, Long.parseLong(key.split(":")[2]))
				);
			}
		}
	}
	
	@PostConstruct
	public void init() {
		initLike();
	}
}
